package com.ld.bisystem.wrapper;


import com.ld.bisystem.util.ReflectionUtil;
import com.ld.bisystem.wrapper.condition.SqlCondition;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * 线程不安全
 * @param
 */
public class AbstWrapper<E extends  AbstWrapper> implements ISqlWrapper {

    private static String Jw_Default_Name="jw.args.";

    private String jwName;

    /**
     * 数据存储
     */
    private Map<String,Object> args;

    private int keyName;

    /**
     * 返回值
     */
    protected StringBuffer sqlSelect;

    /**
     * 数据来源
     */
    protected StringBuffer sqlFrom;

    /**
     * 查询条件
     */
    protected StringBuffer sqlWhere;

    /**
     * 数据分组
     */
    protected StringBuffer sqlGroup;

    /**
     * 分组数据过滤
     */
    protected StringBuffer sqlHaving;


    /**
     * 分组数据过滤
     */
    protected StringBuffer sqlOrder;

    public AbstWrapper(String jwName) {
        this.jwName = jwName;
        this.keyName=0;
        this.args = new HashMap<>();
        this.sqlSelect = new StringBuffer();
        this.sqlFrom = new StringBuffer();
        this.sqlWhere = new StringBuffer();
        this.sqlGroup = new StringBuffer();
        this.sqlHaving = new StringBuffer();
        this.sqlOrder = new StringBuffer();

    }
    public AbstWrapper() {
        this(Jw_Default_Name);
    }


    /**
     * 设置一个值
     * @param val
     * @return
     */
    protected String setValue(Object val){
        StringBuffer sb = new StringBuffer();
        if(val instanceof Collection){
            Collection coll = (Collection)val;
            for (Object o : coll) {
                String key = nextName();
                args.put(key,o);
                if(isNotEmpty(sb)){
                    sb.append(",");
                }
                sb.append(" #{"+jwName+key+"}");
            }
        }else {
            String key = nextName();
            args.put(key,val);

            sb.append(" #{"+jwName+key+"}");
        }

        return sb.toString();
    }

    /**
     * 产生位移名称
     * @return
     */
    protected String nextName(){

        return ""+keyName++;
    }

    protected boolean isNotEmpty(StringBuffer val){
        return val.length() != 0;
    }
    protected boolean isEmpty(StringBuffer val){
        return val.length() == 0;
    }

    @Override
    public String getSqlSegment() {
        StringBuffer sb =  new StringBuffer();
        sb.append("select");
        sb.append(" "+sqlSelect);
        sb.append(" from "+sqlFrom);
        if(isNotEmpty(sqlWhere)){
            sb.append(" where "+sqlWhere);
        }
        if(isNotEmpty(sqlGroup)){
            sb.append(" group by "+sqlGroup);
        }
        if(isNotEmpty(sqlHaving)){
            sb.append(" having "+sqlHaving);
        }
        if(isNotEmpty(sqlOrder)){
            sb.append(" order by  "+sqlOrder);
        }

        return sb.toString();
    }

    protected E select(String column){
        return select("",column,"");
    }
    protected E select(String start,String column,String end){
        if(isNotEmpty(sqlSelect)){
            sqlSelect.append(",");
        }
        sqlSelect.append(start+column+end);
        return (E)this;
    }
    protected E from(String tableName) {
        return from("",tableName);
    }

    protected E from(String joinWhere,String tableName){
        if(isEmpty(sqlFrom)){
            sqlFrom.append(tableName);
        }else {
            sqlFrom.append(" inner join ");
            sqlFrom.append(tableName);
            sqlFrom.append(" on ");
            sqlFrom.append(joinWhere);
        }
        return (E)this;
    }

    public E where(String column, SqlCondition condition, Object value, boolean and){
        //如果是一个集合 则返回多个,分割
        if(ReflectionUtil.isEmpty(value)){
            return (E)this;
        }
        String val = setValue(value);
        if(isNotEmpty(sqlWhere)){
            if(and){
                sqlWhere.append(" and ");
            }else {
                sqlWhere.append(" or ");
            }
        }
        switch (condition){
            case in:{
                sqlWhere.append(column+" "+ condition.getSymbol());
                sqlWhere.append("("+val+")");
                break;
            }case between:{
                val.replace(","," and ");
                sqlWhere.append(column+" "+ condition.getSymbol()+val);
                break;
            }default:{
                sqlWhere.append(column+" "+ condition.getSymbol()+val);
            }

        }

        return (E)this;
    }

    protected E group(String column){
        if(isNotEmpty(sqlGroup)){
            sqlGroup.append(" , ");
        }
        sqlGroup.append(column);
        return (E)this;
    }

    public E having(String column,SqlCondition condition,Object value,boolean and){
        if(ReflectionUtil.isEmpty(value)){
            return (E)this;
        }
        String val = setValue(value);
        if( isNotEmpty(sqlHaving)){
            if(and){
                sqlHaving.append(" and ");
            }else {
                sqlHaving.append(" or ");
            }
        }
        switch (condition){
            case in:{
                sqlHaving.append(column+" "+condition.getSymbol());
                sqlHaving.append(" ("+val+") ");
                break;
            }case between:{

                val =val.replace(","," and ");

                sqlHaving.append(column+" "+condition.getSymbol()+val);
                break;
            }default:{
                sqlHaving.append(column+" "+condition.getSymbol()+val);
            }

        }

        return (E)this;
    }

    protected E order(String column,boolean asc){
        if(sqlOrder.length() != 0){
            sqlOrder.append(" , ");
        }
        sqlOrder.append(column);
        if(asc){
            sqlOrder.append(" asc ");
        }else {
            sqlOrder.append(" desc ");
        }
        return (E)this;
    }

    public Map<String, Object> getArgs() {
        return args;
    }
}
